﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.Runtime.InteropServices;
using System.Threading;

namespace AeroWeather
{
    public partial class AeroWeather : Form
    {
        bool validZipCode;
        string zip;
        int currentTemp = -128;

        static int nightDivisor = 3;

        public AeroWeather()
        {
            InitializeComponent();
            Tray.ContextMenu = mnuTray;
            zip = "";
            validZipCode = false;

            if (!Properties.Settings.Default.firstRun &&
                WeatherAPI.isValidZip(Properties.Settings.Default.zip))
            {
                zip = Properties.Settings.Default.zip;
                validZipCode = true;
                WTimer_Tick(null, null);
            }
            WTimer.Start();
        }

        private void AeroWeather_Shown(object sender, EventArgs e)
        {
            if (!Properties.Settings.Default.firstRun || validZipCode == true)
            {
                LoadFormFromSettings();
                WTimer_Tick(sender, null);
                //this.Hide();
            }
        }

        // This puts all the values back into the form before it hides it.
        private void LoadFormFromSettings()
        {
            tZip.Text = Properties.Settings.Default.zip;
            rTemp.Checked = Properties.Settings.Default.useTemp;
            rConditions.Checked = !Properties.Settings.Default.useTemp;
            tMin.Text = Properties.Settings.Default.min.ToString();
            tMax.Text = Properties.Settings.Default.max.ToString();
            cNightMode.Checked = Properties.Settings.Default.nightMode;
            // this should always work, since we check for a valid zip before we save it.
            bValidate_Click(null, null);
        }

        private void bValidate_Click(object sender, EventArgs e)
        {
            if (WeatherAPI.isValidZip(tZip.Text))
            {
                validZipCode = true;
                zip = tZip.Text;
                lLocation.Text = WeatherAPI.GetCityStateString(zip);
                bOK.Enabled = true;
            }
            else
            {
                zip = "";
                lLocation.Text = "Invalid";
                validZipCode = false;
                bOK.Enabled = false;
            }
        }

        private void tZip_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                bValidate_Click(sender, null);
            }
        }

        private bool ValidateMinMax()
        {
            int min = int.Parse(tMin.Text);
            int max = int.Parse(tMax.Text);

            if (min >= max) return false;
            if (max - min < 20) return false;
            if (max > 110) return false;
            if (min < 0) return false;
            return true;
        }

        private void SaveSettings()
        {
            Properties.Settings.Default.zip = zip;
            Properties.Settings.Default.firstRun = false;
            Properties.Settings.Default.useTemp = rTemp.Checked;
            Properties.Settings.Default.min = int.Parse(tMin.Text);
            Properties.Settings.Default.max = int.Parse(tMax.Text);
            Properties.Settings.Default.Save();
        }

        private void bOK_Click(object sender, EventArgs e)
        {
            if (!ValidateMinMax())
            {
                MessageBox.Show("Unable to validate min/max settings. Ensure:\n\nThe minimum is lower than the maximum.\nThere is at least 20 degrees between the minimum and maximum.\nThe maximum is not over 110 degrees.\nThe minimum is not below 0 degrees.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            this.Hide();
            SaveSettings();
            WTimer_Tick(sender, null);
        }


        private void bCancel_Click(object sender, EventArgs e)
        {
            // if this isn't the first run, we can load the settings from the save to "cancel" the current ones.
            if (!Properties.Settings.Default.firstRun)
            {
                LoadFormFromSettings();
            }
            else
            {
                tZip.Text = string.Empty;
                if (!validZipCode)
                {
                    lLocation.Text = "Not set";
                }
            }
            this.Hide();
        }

        private void WTimer_Tick(object sender, EventArgs e)
        {
            if (!validZipCode) return;

            currentTemp = WeatherAPI.GetCurrentTemperature(zip);
            Tray.Text = "AeroWeather - " + currentTemp + "F";

            if (Properties.Settings.Default.useTemp)
            {
                // Temperature-based 
                Color baseColor = WeatherAPI.GetColorFromTemp(Properties.Settings.Default.min, Properties.Settings.Default.max, WeatherAPI.GetCurrentTemperature(zip));
                DateTime rise = WeatherAPI.GetSunrise(zip);
                DateTime sunset = WeatherAPI.GetSunset(zip);

                // If night mode is set, and we are not in the daytime
                if (cNightMode.Checked && !(DateTime.Now > rise && DateTime.Now < sunset))
                {
                    Color nColor = Color.FromArgb((int)baseColor.R / nightDivisor, (int)baseColor.G / nightDivisor, (int)baseColor.B / nightDivisor);
                    Dwm.ChangeColor(nColor);
                }
                else
                {

                    Dwm.ChangeColor(baseColor);
                }
            }
            else
            {
                // Condition-based
                Dwm.ChangeColor(WeatherAPI.GetColorFromConditions(WeatherAPI.GetCurrentConditions(zip)));
            }
        }

        private void Tray_DoubleClick(object sender, EventArgs e)
        {
            this.Show();
        }

        private void tMin_KeyPress(object sender, KeyPressEventArgs e)
        {
            int isNumber = 0;
            e.Handled = !int.TryParse(e.KeyChar.ToString(), out isNumber);
        }

        private void mnuExit_Click(object sender, EventArgs e)
        {
            Tray.Visible = false;
            Environment.Exit(0);
        }

        private void mnuConfigure_Click(object sender, EventArgs e)
        {
            this.Show();
        }

        private void mnuAbout_Click(object sender, EventArgs e)
        {

        }


    }


}
